/**
 * @Auther: lichao
 * @Date: 2024/10/18 - 10 - 18 - 10:00
 * @Description: PACKAGE_NAME
 * @version: 1.0
 */

import java.nio.charset.StandardCharsets;

/**
 * @program: java
 * @description: String 构造函数学习
 * @author: lichao
 * @create: 2024-10-18 10:00
 **/

public class ConstructorStudy {
    public static void main(String[] args) {
        /**
         * String() 初始化新创建的String对象，使其表示空字符序列。请注意，由于字符串是不可变的，因此不需要使用此构造函数。
         */
        String str1 = new String();
        System.out.println(str1); // 空

        /**
         * String(byte[] bytes) 通过使用默认字符集解码字节数组来构造一个新的String。新String的长度取决于字符集，因此可能不等于字节数组的长度。
         *  bytes - 要解码为字符的字节
         */
        byte[] bytes = "abcd".getBytes(StandardCharsets.UTF_8);
        String str2 = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(str2); // abcd

        /**
         * String(byte[] bytes, String  charsetName) 同上
         */

        /**
         * String(byte[] bytes, Charset charset) 同上
         *  bytes: 包含要转换为字符串的字节数组。
         *  charset: 用于解码字节的 Charset 对象，常用的有 StandardCharsets.UTF_8、StandardCharsets.ISO_8859_1 等
         */

        /**
         * String(byte[] bytes, int offset, int length)
         * 通过使用默认字符集解码字节数组的指定子数组来构造一个新的String。新String的长度取决于字符集，因此可能不等于子数组的长度
         *  bytes - 要解码为字符的字节
         *  offset - 要解码的第一个字节的索引
         *  length - 要解码的字节数
         */
        byte[] bytes2 = "abcdef".getBytes(StandardCharsets.UTF_8);
        String str3 = new String(bytes2, 1, 3);
        System.out.println(str3); // bcd

        /**
         * String(byte[] bytes, int offset, int length, String charsetName)
         * 通过使用指定字符集解码字节数组的指定子数组来构造一个新的String。新String的长度取决于字符集，因此可能不等于子数组的长度。
         *  bytes - 要解码为字符的字节
         *  offset - 要解码的第一个字节的索引
         *  length - 要解码的字节数
         *  charset - 用于解码字节的 Charset 对象，常用的有 StandardCharsets.UTF_8、StandardCharsets.ISO_8859_1 等
         */
        byte[] bytes3 = "Hello World".getBytes(StandardCharsets.UTF_8);
        String str4 = new String(bytes3, 3, 6, StandardCharsets.UTF_8);
        System.out.println(str4); // lo Wor

        /**
         * String(byte[] bytes, int offset, int length, Charset charset) 同上
         */

        /**
         *  String(char[] value) 分配一个新的String，以表示当前包含在字符数组参数中的字符序列。字符数组的内容将被复制；对字符数组的后续修改不会影响新创建的字符串。
         *
         */
        char[] chars = {'h', 'o', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
        String str5 = new String(chars);
        System.out.println(str5); // holloworld

        /**
         * String(char[] value, int offset, int length) 分配一个新的String，其中包含字符数组参数的子数组中的字符。子数组的内容将被复制；对字符数组的后续修改不会影响新创建的字符串。
         *  value - 作为字符源的数组
         *  offset - 初始偏移量
         *  count - 长度
         */
        char[] chars1 = {'h', 'o', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
        String str6 = new String(chars1, 3, 6);
        System.out.println(str6); // loworl

        /**
         * String(int[] codePoints, int offset, int length) 分配一个新的String，其中包含Unicode代码点数组参数的子数组中的字符。子数组的内容将转换为char；对int数组的后续修改不会影响新创建的字符串。
         *  codePoints: 一个整数数组，每个整数代表一个 Unicode 代码点。
         *  offset: 从数组中开始读取代码点的起始索引。
         *  length: 要读取的代码点的数量。
         */
        // 定义一个 Unicode 代码点数组
        int[] codePoints = { 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33 };
        String str7 = new String(codePoints, 0, codePoints.length);
        System.out.println(str7); // Hello, World!

        /**
         * String(String original) 初始化新创建的String对象，使其表示与参数相同的字符序列；换句话说，新创建的字符串是参数字符串的副本。除非需要显式复制original，否则不需要使用此构造函数，因为字符串是不可变的
         */

        /**
         * String(StringBuffer buffer) 分配一个新的字符串，其中包含当前包含在字符串缓冲区参数中的字符序列。字符串缓冲区的内容将被复制；随后对字符串缓冲区的修改不会影响新创建的字符串
         * 使用的场景：
         *  1、在构建复杂的字符串时，你可以使用 StringBuffer 进行各种修改操作，然后在完成构建后将其转换为 String
         *  2、在需要线程安全的字符串构建和修改场景下，StringBuffer 是一种有效的选择。完成后，使用 String 构造函数将最终的结果获取为不可变的字符串。
         */

        StringBuffer sb =  new StringBuffer();
        sb.append("hello");
        sb.append("world");
        String str8 = new String(sb);
        System.out.println(str8); // helloworld

        /**
         * String(StringBuilder builder) 分配一个新的字符串，其中包含当前包含在字符串构建器参数中的字符序列。字符串构建器的内容将被复制；随后对字符串构建器的修改不会影响新创建的字符串。
         *  跟 StringBuffer 的区别：
         *      StringBuilder 是非线程安全的，适用于单线程环境。对于多线程环境，使用 StringBuffer 是更安全的选择，因为 StringBuffer 是线程安全的
         *  使用场景：
         *      1、动态字符串构建: StringBuilder 特别适合在循环或条件语句中动态构建字符串。当所有修改完成后，使用 String 构造函数获取最终字符串。
         *      2、性能优化: 如果在性能敏感的应用中需要频繁修改字符串，优先使用 StringBuilder 来构建字符串，然后在需要时将其转换为 String。
         */
        StringBuilder sb2 = new StringBuilder();
        sb2.append("hello");
        sb2.append("world");
        String str9 = new String(sb2);
        System.out.println(str9); // helloworld
    }
}
